module hdmi_driver1280x720(
    input sys_rst_n,    //复位信号
    input pixel_clk,

    input vga_mode,
    input blockvga,
    
    output reg       read_line_req ,
    input            read_line_ack ,
    output reg       read_line_part,
    output           read_line_A_B ,//1:A 0:B
    output    [15:0] read_line_addr,//4kline total
    input     [15:0] read_line_base_addr,//start line

    input [15:0] read_pixelA_data,
    input [15:0] read_pixelB_data,
    output [9:0] read_pixel_addr,
    output       read_pixel_clk,

    input  [9:0] cursor_posX,//0~1024
    input  [9:0] cursor_posY,//0~1024
    input [15:0] read_cursor_data,
    output [9:0] read_cursor_addr,//32 * 32
    output       read_cursor_clk,
    
    //VGA接口
    //output     reg     vga_hs,       //行同步信号
    //output     reg     vga_vs,       //场同步信号
    //output  [15:0]  vga_rgb      //红绿蓝三原色输出
    
    output          video_hs,
    output          video_vs,
    output          video_de,
    output reg [23:0] video_rgb

  );

//1024*768 60FPS_65MHz
localparam  H_SYNC   =  11'd10;   //行同步
localparam  H_BACK   =  11'd10;  //行显示后沿
localparam  H_DISP   =  11'd1280; //行有效数据
localparam  H_FRONT  =  11'd10;  //行显示前沿
localparam  H_TOTAL  =  11'd1310; //行扫描周期 d1650
localparam  H_BLANK  =  11'd128; //行扫描周期 d1650
localparam  H_FRAME_START = H_SYNC+H_BACK+H_BLANK;

localparam  V_SYNC   =  11'd5;    //场同步
localparam  V_BACK   =  11'd10;   //场显示后沿
localparam  V_DISP   =  11'd720;  //场有效数据
localparam  V_FRONT  =  11'd5;    //场显示前沿
localparam  V_TOTAL  =  11'd740;  //场扫描周期
localparam  V_BLANK  =  11'd0;  //场扫描周期
localparam  V_FRAME_START = V_SYNC+V_BACK+V_BLANK;

assign video_hs  = ( cnt_h < H_SYNC ) ? 1'b0 : 1'b1;
assign video_vs  = ( cnt_v < V_SYNC ) ? 1'b0 : 1'b1;

assign video_de  = (((cnt_h >= H_SYNC+H_BACK) && (cnt_h < H_SYNC+H_BACK+H_DISP))
                 &&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
                 ?  1'b1 : 1'b0;

localparam WHITE  = 24'b11111111_11111111_11111111;  //RGB888 ��ɫ
localparam GREEN  = 24'b00000000_11111111_00000000;  //RGB888 ��ɫ

wire [10:0]  pixel_xpos = cnt_h - (H_SYNC + H_BACK);
wire [10:0]  pixel_ypos = cnt_v - (V_SYNC + V_BACK);

wire [10:0] pixel_xpos2 = pixel_xpos - H_BLANK;
parameter H_DISP2 = 1024;
always @(*) begin
  if(video_de)begin
    if(pixel_xpos < H_BLANK-1)begin
        video_rgb <= WHITE;
    end else if(pixel_xpos == H_BLANK-1)begin
        video_rgb <= GREEN;
    end else if(pixel_xpos > (H_DISP-H_BLANK))begin
        video_rgb <= WHITE;
    end else if(pixel_xpos == (H_DISP-H_BLANK))begin
        video_rgb <= GREEN;
    end else begin
      video_rgb <= {pixel_data[15:11],3'b0,pixel_data[10:5],2'b0,pixel_data[4:0],3'b0};
    end
  end else begin
    video_rgb <= 24'd0;
  end
end

assign read_pixel_clk = pixel_clk;
assign read_cursor_clk = pixel_clk;
reg h_active;
reg v_active;
reg v_active_ram;

//reg define
reg  [10:0] cnt_h;
reg  [10:0] cnt_v;


wire showCursor = (dotPosX >= cursor_posX) && (dotPosX < (cursor_posX + 32)) && (dotPosY >= cursor_posY) && (dotPosY < (cursor_posY + 32));

reg [15:0] latch_read_line_base_addr;

//当前行-1，读取0行
wire [10:0] offset = dotPosY + 1'b1;//读取下一行
assign read_line_addr = latch_read_line_base_addr + offset;
assign read_line_A_B = offset[0];

wire [15:0] pixel_data = blockvga ? 16'b0 : ((showCursor && read_cursor_data != 0) ? read_cursor_data : ( read_line_A_B ? read_pixelB_data : read_pixelA_data ) );//正在读A行，使用B行的pixel

assign read_pixel_addr = dotPosX[9:0]+1'b1;
assign read_cursor_addr = {cursorPixX,cursorPixY};
//字符模式：
//80*30
//128*32:4096byte //BUFFA BUFFB
//8*16 char table 
//16byte per char
//128char = 2048byte
//提前2周期取字符，提前1周期取像素，8周期显示像素

wire [4:0] cursorPixX = dotPosX[4:0] - cursor_posX[4:0] + 1'b1;
wire [4:0] cursorPixY = dotPosY[4:0] - cursor_posY[4:0];

wire [10:0] dotPosX = cnt_h - H_FRAME_START;
wire [10:0] dotPosY = cnt_v - V_FRAME_START;

reg read_line_ack_buff;
reg [1:0] read_line_status;
always @(posedge pixel_clk or negedge sys_rst_n) begin
  if (!sys_rst_n)begin
    cnt_h <= 0;
    cnt_v <= 0;
    read_line_req <= 0;
    read_line_ack_buff <= 0;
    read_line_status <= 0;
  end else begin
    read_line_ack_buff <= read_line_ack;
  
    cnt_h <= cnt_h + 1'b1;
    if(cnt_h == H_TOTAL)begin
      cnt_h <= 10'd0;
      cnt_v <= cnt_v + 1'b1;
      if(cnt_v == V_TOTAL)begin
        cnt_v <= 10'd0;
      end
    end
    
    if(cnt_v == 0)begin
      latch_read_line_base_addr <= read_line_base_addr;
    end

    case(read_line_status)
    0:begin
      if(cnt_h == 1 && !blockvga)begin
        if((cnt_v >= V_FRAME_START - 1) && (cnt_v < (V_SYNC+V_BACK+V_DISP-V_BLANK)))begin
         read_line_req <= 1'b1;
         read_line_part <= 0;
         read_line_status <= 1;
        end
      end
    end
    1:begin
      if(read_line_ack_buff)begin
        read_line_req <= 0;
        read_line_status <= 2;
      end
      end
    2:begin
      if(!read_line_ack_buff)begin
        read_line_req <= 1;
        read_line_part <= 1;
        read_line_status <= 3;
      end
    end
    3:begin
      if(read_line_ack_buff)begin
        read_line_req <= 0;
        read_line_status <= 0;
      end
    end
    endcase
  end
end

endmodule 